package com.teufandsub.socialproximity.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.acra.ACRA;
import org.json.JSONObject;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.sax.StartElementListener;
import android.util.Log;
import android.widget.Toast;

import com.teufandsub.socialproximity.R;
import com.teufandsub.socialproximity.gui.ChattingActivity;
import com.teufandsub.socialproximity.gui.LoginActivity;
import com.teufandsub.socialproximity.logic.AuthenticationInfo;
import com.teufandsub.socialproximity.logic.ChatConversation;
import com.teufandsub.socialproximity.logic.Friend;
import com.teufandsub.socialproximity.logic.Message;
import com.teufandsub.socialproximity.logic.RegistrationInfo;
import com.teufandsub.socialproximity.logic.User;
import com.teufandsub.socialproximity.services.HttpService;

public class Controller {
	
	//ACRA.getErrorReporter().handleException(e);

	private static final Controller controller=new Controller();
	private ArrayList<Friend> friends = new ArrayList<Friend>();
	private ArrayList<ChatConversation> alConversations = new ArrayList<ChatConversation>();
	private int notifId = 0;
	private String regId;                                             
	
	public static Controller getInstance(){
		return controller;
	}
	
	/** Return user after a research **/
	public ArrayList<Friend> getResultList(){
		return friends;
	}
	
	public void setConnectedUserList(ArrayList<Friend> list){
		friends=list;
	}
	
	/** Return is the conversation is a new conversation or not **/
	public boolean isNewConversation(User friend){
		for(ChatConversation convers : alConversations){
			if(convers.getFriend().equals(friend)){
				return false;
			}
		}
		return true;
	}
	
	/** Create a new conversation **/
	public ChatConversation newConversation(User user){
		ChatConversation convers = new ChatConversation(user);
		alConversations.add(convers);
		return convers;
	}
	
	public ChatConversation getConversationByUser(User user){
		Iterator<ChatConversation> it = alConversations.iterator();
		ChatConversation convers=it.next();
		
		while(it.hasNext() && !convers.getFriend().equals(user)){
			convers=it.next();
		}
		return convers;
	}

	public ArrayList<ChatConversation> getAlConversations() {
		return alConversations;
	}
	
	/* Return informations about the View on the top */
    public ComponentName getTopComponent(Context context) {

        try {
            ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningTaskInfo> localList = activityManager.getRunningTasks(1);

            if ((localList == null) || (localList.isEmpty())) {
                return null;
            }

            ComponentName localComponentName = ((ActivityManager.RunningTaskInfo) localList.get(0)).topActivity;

            return localComponentName;

        } catch (Exception e) {
        	Log.e(Constants.APP_NAME, e.toString());
            return null;
        }
    }
    
	public void receiveMessage(Context context, Message message){
		Friend author = new Friend(message.getAuthor());
		ChatConversation convers;
		ComponentName localComponentName = getTopComponent(context);
		
		if(isNewConversation(author)){
			convers = newConversation(author);
		}else{
			convers = getConversationByUser(author);
		}
		convers.addMessage(message);
		if(localComponentName.getClassName().equals(Constants.PACKAGE_NAME+".gui.ChattingActivity")
				&& convers.isActive()){
			/* Refresh of the view */
			Runnable run = new Runnable() {
				
				@Override
				public void run() {
					ChattingActivity.getInstance().update();
					
				}
			};
			ChattingActivity.getInstance().runOnUiThread(run);
		}else{
			/* Notification */
			
			Intent intent = new Intent(context, ChattingActivity.class);
			intent.putExtra(Friend.KIND, new Friend(message.getAuthor()));
			PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
			
			Notification noti = new Notification(R.drawable.ic_launcher, context.getResources().getString(R.string.message_received)+ " " + message.getAuthor()
					, System.currentTimeMillis());
			noti.setLatestEventInfo(context, context.getResources().getString(R.string.message_received)+ " " + message.getAuthor() ,
					message.getContent(), pi);
			notify(context, noti);
		}	
		
	}
	
	public JSONObject sendMessage(Context context, Message message){
		return message.send(context);
	}
	
	public int register(Context context, RegistrationInfo regInfo){
		return regInfo.send(context);
	}
	
	public JSONObject authentication(Context context, AuthenticationInfo autInfo){
		return autInfo.send(context);
	}

	public String getRegId() {
		return regId;
	}

	public void setRegId(String regId) {
		this.regId = regId;
	}
	
	public void initSessionId(Context context, String sessionId, String username){
		SharedPreferences settings = context.getSharedPreferences(Constants.PREFS_NAME, 0);
		SharedPreferences.Editor editor = settings.edit();
		editor.putString(Constants.SESSIONID_NAME, sessionId);
		editor.putString(User.USERNAME_NAME, username);
		editor.commit();
		Log.i(Constants.APP_NAME, "Session Id store");
	}
	
	public String[] getSessionInfo(Context context){
		SharedPreferences settings = context.getSharedPreferences(Constants.PREFS_NAME, 0);
		String sessionArray[] = new String[2];
		sessionArray[0] = settings.getString(Constants.SESSIONID_NAME, "");
		sessionArray[1] = settings.getString(User.USERNAME_NAME, "");
		return sessionArray;
	}
	
	public JSONObject getSessionInfoFromServer(Context context,String sessionId, String username, String regId){	
		HttpService service = new HttpService(context);
		return service.getSessionInformations(sessionId, username, regId);	
	}
	
	public boolean checkSession(final Context context, final Class<?> dir){
		final String info[] = getSessionInfo(context);
		boolean returnValue;
		if(!info[0].equals("")){
			returnValue=true;
			AsyncTask<Void, Void, JSONObject> task = new AsyncTask<Void, Void, JSONObject>() {
				
				@Override
				protected JSONObject doInBackground(Void... params) {
					return controller.getSessionInfoFromServer(context,info[0], info[1], controller.getRegId());
				}
				
				@Override
				protected void onPostExecute(JSONObject result) {
					super.onPostExecute(result);
					int code;
					try {
						code = result.getInt(Constants.CODE_NAME);
					} catch (Exception e) {
						code = Constants.CODE_ERROR;
						Log.e(Constants.APP_NAME, "Error to retrieve session informations : " + e.toString());
					}
					
					if(Constants.CODE_SESSION_VALID==code){
						Intent i = new Intent(context, dir);
						i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
						context.startActivity(i);							
					}else{
						Intent i = new Intent(context, LoginActivity.class);
						context.startActivity(i);
					}
				}			
			};
			
			if(Utils.hasConnectivity(context)){
				task.execute();
			}else{
				Toast.makeText(context, context.getResources().getString(R.string.no_connectivity)
						, Toast.LENGTH_LONG).show();
			}
		}else{
			returnValue=false;
		}
		return returnValue;
	}
	
	public JSONObject getConnectedUsers(Context context,final JSONObject info){
		HttpService service = new HttpService(context);
		
		String[] prefs = getSessionInfo(context);
		try {
			info.put(Constants.SESSIONID_NAME, prefs[0]);
			info.put(User.USERNAME_NAME, prefs[1]);
		} catch (Exception e) {
			return null;
		}
		return service.getConnectedUsers(info);
	}
	
	public JSONObject getLists(Context context){
		HttpService service = new HttpService(context);	
		String[] prefs = getSessionInfo(context);
		
		return service.getLists(prefs[0], prefs[1]);
	}
	
	public JSONObject manageFriend(Context context, JSONObject info){
		HttpService service = new HttpService(context);
		
		String[] prefs = getSessionInfo(context);
		try {
			info.put(Constants.SESSIONID_NAME, prefs[0]);
			info.put(User.USERNAME_NAME, prefs[1]);
		} catch (Exception e) {
			return null;
		}
		return service.manageFriend(info);
	}
	
	public void updateLocation(Context context, double latitude, double longitude){
		HttpService service = new HttpService(context);
		JSONObject location = new JSONObject();
		
		String[] prefs = getSessionInfo(context);
		if(!prefs[0].isEmpty()){
			try {
				location.put(Constants.SESSIONID_NAME, prefs[0]);
				location.put(User.USERNAME_NAME, prefs[1]);
				location.put(User.LATITUDE_NAME, latitude);
				location.put(User.LONGITUDE_NAME, longitude);
			} catch (Exception e) {
				Log.e(Constants.APP_NAME, "Probleme to generate location JSONObject : " + e.toString());
			}
			
			service.updateLocation(location);
		}	
	}
	
	public void stayActive(Context context, boolean stayActive){
		HttpService service = new HttpService(context);	
		String[] prefs = getSessionInfo(context);
		
		service.stayActive(prefs[0], prefs[1], stayActive);
	}
	
	public void notify(Context context, Notification noti){
		NotificationManager mg = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		
		noti.vibrate = new long[]{100, 200, 100, 500}; 
		noti.number=notifId++;
		noti.flags |= Notification.FLAG_AUTO_CANCEL;
		mg.notify(notifId, noti);
	}
	
	public void disconnect(Context context){
		SharedPreferences settings = context.getSharedPreferences(Constants.PREFS_NAME, 0);
		SharedPreferences.Editor editor = settings.edit();
		editor.clear();
		editor.apply();
		
		Intent intent = new Intent(context, LoginActivity.class);
		intent.putExtra("from", context.getClass().getName());
		context.startActivity(intent);
	}
}
